#include "Thread.h"
#include <iostream>
#include <sstream>
#include <chrono>
#include <thread>

#ifdef _WIN32
#include <windows.h>
#else
#include <sys/syscall.h>
#include <unistd.h>
#include <pthread.h>
#endif

namespace cytoolkit {
std::atomic<int> Thread::numCreated_{0};

Thread::Thread(ThreadFunc func, const std::string& name)
    : started_(false),
      joined_(false),
      func_(std::move(func)),
      name_(name)
{
    numCreated_++;
    if (name_.empty()) {
        setDefaultName();
    }
}

Thread::Thread(Thread&& other) noexcept
    : started_(other.started_),
      joined_(other.joined_),
      thread_(std::move(other.thread_)),
      tid_(other.tid_),
      func_(std::move(other.func_)),
      name_(std::move(other.name_))
{
    other.started_ = false;
    other.joined_ = false;
}

Thread& Thread::operator=(Thread&& other) noexcept
{
    if (this != &other) {
        if (thread_ && thread_->joinable()) {
            thread_->detach();
        }
        
        started_ = other.started_;
        joined_ = other.joined_;
        thread_ = std::move(other.thread_);
        tid_ = other.tid_;
        func_ = std::move(other.func_);
        name_ = std::move(other.name_);
        
        other.started_ = false;
        other.joined_ = false;
    }
    return *this;
}

Thread::~Thread()
{
    if (thread_ && !joined_ && thread_->joinable()) {
        thread_->detach(); // 避免线程未分离导致terminate
    }
}

void Thread::setDefaultName()
{
    std::ostringstream oss;
    oss << "Thread-" << numCreated_;
    name_ = oss.str();
}

void Thread::start()
{
    if (started_) {
        return; // 避免重复启动
    }
    
    started_ = true;
    
    // 使用lambda包装线程执行，确保正确的同步
    thread_ = std::make_unique<std::thread>([this]() {
        {
            std::lock_guard<std::mutex> lock(mutex_);
            tid_ = std::this_thread::get_id();
            ready_ = true;
        }
        cond_.notify_all();
        
        runInThread();
    });
    
    // 等待线程真正启动
    std::unique_lock<std::mutex> lock(mutex_);
    cond_.wait(lock, [this]() { return ready_; });
}

bool Thread::join()
{
    if (thread_ && thread_->joinable() && !joined_) {
        thread_->join();
        joined_ = true;
        return true;
    }
    return false;
}

void Thread::detach()
{
    if (thread_ && thread_->joinable()) {
        thread_->detach();
    }
}

void Thread::runInThread()
{
    try {
        if (func_) {
            func_(); // 执行用户函数
        }
    } catch (const std::exception& ex) {
        std::cerr << "Exception in thread " << name_ << ": " << ex.what() << std::endl;
    } catch (...) {
        std::cerr << "Unknown exception in thread " << name_ << std::endl;
    }
}

void Thread::usleep(int us)
{
    std::this_thread::sleep_for(std::chrono::microseconds(us));
}

void Thread::msleep(int ms)
{
    std::this_thread::sleep_for(std::chrono::milliseconds(ms));
}

int Thread::threadID()
{
#ifdef _WIN32
    return static_cast<int>(GetCurrentThreadId());
#else
    return static_cast<int>(syscall(SYS_gettid));
#endif
}

bool Thread::setAffinity(int cpuId)
{
#ifdef _WIN32
    DWORD_PTR mask = 1ULL << cpuId;
    return SetThreadAffinityMask(GetCurrentThread(), mask) != 0;
#else
    cpu_set_t cpuset;
    CPU_ZERO(&cpuset);
    CPU_SET(cpuId, &cpuset);
    return pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset) == 0;
#endif
}

void Thread::setName(const std::string& name)
{
#ifdef _WIN32
    SetThreadDescription(GetCurrentThread(), name.c_str());
#else
    pthread_setname_np(pthread_self(), name.c_str());
#endif
}

} // namespace cytoolkit